package decisiontree;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

public class NoTree<Email>{
	
	protected String atribute;
	protected String classification;
	protected String padrao = "No";
	protected NoTree<Email> haschildren;
	protected NoTree<Email> hasntchildren;
	protected Hashtable<String, Integer> characteristcUniversal;
	protected String returntree;
	protected Vector<Vector<Integer>> characteristicpositive;
	protected Vector<Vector<Integer>> characteristicnegative;
	
	
	public NoTree(Hashtable<String, Integer> characteristcUniversal, Vector<Vector<Integer>> characteristicpositive, Vector<Vector<Integer>> characteristicnegative){
		
		this.classification = null;
		this.characteristcUniversal = characteristcUniversal;
		this.characteristicpositive = characteristicpositive;
		this.characteristicnegative = characteristicnegative;		
	}
	
	public void analise(String m) throws Exception{
	
		Hashtable<String, Integer> universal = (Hashtable<String, Integer>) characteristcUniversal.clone();
		Vector<Vector<Integer>> poshasatribute = new Vector<Vector<Integer>>(); //Example positive which has atribute
		Vector<Vector<Integer>> neghasatribute = new Vector<Vector<Integer>>();
		
		Hashtable<String, Integer> universal2 = (Hashtable<String, Integer>) characteristcUniversal.clone();
		Vector<Vector<Integer>> poshasntatribute = new Vector<Vector<Integer>>();
		Vector<Vector<Integer>> neghasntatribute = new Vector<Vector<Integer>>();
		
		//verifyClassification();
		
		if ((characteristicpositive.size() == 0) && (characteristicnegative.size() == 0))
			classification = padrao;
		else if(equalsClassification())
		{}
		else if(characteristcUniversal.size() == 0)
			classification = valueMost();
		else{
			atribute = bestAtribute();
			m = valueMost();
			
			hasAtribute(atribute, characteristicpositive, poshasatribute, poshasntatribute);
			hasAtribute(atribute, characteristicnegative, neghasatribute, neghasntatribute);
			
			universal.remove(atribute);
			haschildren = new NoTree<Email>(universal, poshasatribute, neghasatribute);
			haschildren.analise(m);
						
			universal2.remove(atribute);
			hasntchildren = new NoTree<Email>(universal2, poshasntatribute, neghasntatribute);
			hasntchildren.analise(m);
		}
	}

	private String bestAtribute() throws Exception {
		String bestatribute = null;
		double gain = 0, tempgain;
		
		int atribute;
		String atributename;
		
		Vector<Integer> temp;
		Enumeration<String> elements = characteristcUniversal.keys();
		int positiveyes, positiveno, negativeyes, negativeno;
		
		while(elements.hasMoreElements()){
			positiveyes = 0;
			positiveno = 0;
			negativeyes = 0;
			negativeno = 0;
			
			atributename = elements.nextElement();
			
			atribute = characteristcUniversal.get(atributename);
			for(int i = 0;i < characteristicpositive.size();i++){
				temp = characteristicpositive.get(i);
				if(temp.contains(atribute))
					positiveyes++;
				else
					positiveno++;
			}
			for(int i = 0;i < characteristicnegative.size();i++){
				temp = characteristicnegative.get(i);
				if(temp.contains(atribute))
					negativeyes++;
				else
					negativeno++;
			}
			//tempgain = DecisionTree.gain(positiveyes, positiveno, negativeyes, negativeno);
			tempgain = DecisionTree.gain(positiveyes, negativeyes, positiveno, negativeno);
			if((bestatribute == null) || ((tempgain == gain) && verifyPriority(bestatribute, atributename)) || tempgain > gain){
				gain = tempgain;
				bestatribute = atributename;
			}
		}
		return bestatribute;
	}

	private String valueMost() {
		if(characteristicpositive.size() > characteristicnegative.size())
			return "Yes";
		else
			return "No";
	}

	//Informa se deve trocar
	public boolean verifyPriority(String best, String candidate) throws Exception{
		String hearderbest = best.split(":")[0];
		String heardercandidate = candidate.split(":")[0];
		
		int valorbest, valorcandidate;
		
		if(hearderbest.equals("from"))
			valorbest = 4;
		else if(hearderbest.equals("subject"))
			valorbest = 3;
		else if(hearderbest.equals("list"))
			valorbest = 2;
		else if(hearderbest.equals("to"))
			valorbest = 1;
		else if(hearderbest.equals("cc"))
			valorbest = 0;
		else
			throw new Exception("NoTree: Unrecognized field");
		
		if(heardercandidate.equals("from"))
			valorcandidate = 4;
		else if(heardercandidate.equals("subject"))
			valorcandidate = 3;
		else if(heardercandidate.equals("list"))
			valorcandidate = 2;
		else if(heardercandidate.equals("to"))
			valorcandidate = 1;
		else if(heardercandidate.equals("cc"))
			valorcandidate = 0;
		else
			throw new Exception("NoTree: Unrecognized field");
		
		if(valorbest >= valorcandidate)
			return false;
		else
			return true;
	}
	
	public void hasAtribute(String atribute, Vector<Vector<Integer>> characteristic, Vector<Vector<Integer>> hasatribute, Vector<Vector<Integer>> hasntatribute){
		Vector<Integer> temp;
		
		int value = characteristcUniversal.get(atribute);
		
		for(int i = 0;i < characteristic.size(); i++){
			temp = characteristic.get(i);
			if(temp.contains(value)){
				hasatribute.add(temp);
			}else{
				hasntatribute.add(temp);
			}
		}
				
	}
	
	public boolean equalsClassification(){
		if(characteristicnegative.size() == 0){
			classification = "Yes";
			return true;
		}else if(characteristicpositive.size() == 0){
			classification = "No";
			return true;
		}else
			return false;
	}
	
	public String toString(int nivel){
		String returnstring;
		String recuo = "";
		
		for(int i = 0;i < nivel;i++){
			recuo += "|\t";
		}
		
		if(classification != null)
			returnstring = classification;
		else{
			returnstring = "Node: "+atribute+"\n"+recuo+"Positive: "+haschildren.toString(nivel + 1)+"\n"+recuo+"Negative: "+hasntchildren.toString(nivel + 1);
		}
		return returnstring;
		
	}
	
	public String getFilter(){
		String returnFilter = "";
		boolean boolpositive = false;
		if(haschildren.classification == null)
			returnFilter += " ("+atribute + " "+haschildren.getFilter() + ")";
		else if(haschildren.classification.equals("Yes")){
			boolpositive = true;
			returnFilter += atribute;
		}
		
		if(hasntchildren.classification == null){
			if(boolpositive){
				returnFilter = "(" + returnFilter + " OR ";
			}
			returnFilter += hasntchildren.getFilter() + ")";
		}else if(hasntchildren.classification.equals("Yes")){
			if(boolpositive)
				returnFilter += " OR ";
			returnFilter += "-" + atribute;
		}
		
		return returnFilter;
	}
}
